package com.server.http.controller;

import com.server.dao.MobileAppAlarmDao;
import com.server.dao.MobileAppDao;
import com.server.dao.MobileAppUnitDao;
import com.server.dao.UnitDao;
import com.server.http.anYuan.AnYuanServer;
import com.server.http.controller.dto.RegisterDto;
import com.server.http.service.MobileAppService;
import com.server.http.service.UnitService;
import com.server.libs.EmailCode.BindEmailCode;
import com.server.libs.EmailCode.ForgetPasswordEmailCode;
import com.server.libs.EmailCode.UnbindEmailCode;
import com.server.libs.login.AppAuth;
import com.server.libs.login.AppOline;
import com.server.libs.ret.R;
import com.server.libs.ret.RE;
import com.server.pojo.Alarm;
import com.server.pojo.MobileApp;
import com.server.pojo.MobileAppUnit;
import com.server.pojo.Unit;
import com.server.push.dto.resp.LogoutOP;
import com.server.push.OnlinePush;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@RestController
@RequestMapping(value = "/mobileApp")
@Slf4j
@Transactional
public class MobileAppController {
    @Autowired
    MobileAppDao mobileAppDao;
    @Autowired
    UnitDao unitDao;

    @Autowired
    MobileAppUnitDao mobileAppUnitDao;

    @Autowired
    AppAuth appAuth;

    @Autowired
    MobileAppService mobileAppService;

    @Autowired
    UnitService unitService;

    @Autowired
    BindEmailCode bindEmailCode;

    @Autowired
    UnbindEmailCode unbindEmailCode;

    @Autowired
    ForgetPasswordEmailCode forgetPasswordEmailCode;

    @Autowired
    JavaMailSender mail;

    @Autowired
    MobileAppAlarmDao mobileAppAlarmDao;

    @Autowired
    OnlinePush onlinePush;

    @Autowired
    AppOline appOline;



    @RequestMapping(value = "/bind/email/code",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> getCode(@RequestHeader String authorization,
                             @RequestBody Map<String,Object> map) {
        String email = (String) map.get("email");

        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        String code = bindEmailCode.create(email,mobileApp);
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject("【警保联动】邮箱绑定");
        message.setText("您本次注册的验证码为："+code+" (请在十分钟内完成绑定！)");
        message.setFrom("1563782247@qq.com");
        message.setTo(email);
        try {
            mail.send(message);
            return new R<>("发送成功！");

        }catch (MailException ignored){
            bindEmailCode.del(email,mobileApp);
            throw new RE("发送失败，请检查邮箱是否正确！");
        }

    }

    @RequestMapping(value = "/bind/email",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> bindEmail(@RequestHeader String authorization,
                               @RequestBody Map<String,Object> map) {
        String email = (String) map.get("email");
        String code = (String) map.get("code");

        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        bindEmailCode.check(email,code,mobileApp);

        mobileApp.setEmail(email);
        mobileAppDao.save(mobileApp);

        return new R<>("绑定成功");
    }

    @RequestMapping(value = "/unbind/email/code",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> unbindCode(@RequestHeader String authorization,
                                @RequestBody Map<String,Object> map) {
        String email = (String) map.get("email");

        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        String code = unbindEmailCode.create(email,mobileApp);
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject("【警保联动】邮箱解绑");
        message.setText("您本次注册的验证码为："+code+" (请在十分钟内完成解绑！)");
        message.setFrom("1563782247@qq.com");
        message.setTo(email);
        try {
            mail.send(message);
            return new R<>("发送成功！");

        }catch (MailException ignored){
            unbindEmailCode.del(email,mobileApp);
            throw new RE("发送失败，请检查邮箱是否正确！");
        }

    }

    @RequestMapping(value = "/unbind/email",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> unbindEmail(@RequestHeader String authorization,
                                 @RequestBody Map<String,Object> map) {
        String email = (String) map.get("email");
        String code = (String) map.get("code");

        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        unbindEmailCode.check(email,code,mobileApp);

        mobileApp.setEmail(null);
        mobileAppDao.save(mobileApp);

        return new R<>("解绑成功");
    }

    @RequestMapping(value = "/forget/byEmail/code",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> updatePasswordGetCode(@RequestBody Map<String,Object> map) {
        String email = (String) map.get("email");
        if (!email.matches("^([a-zA-Z]|[0-9])(\\w|\\-)+@[a-zA-Z0-9]+\\.([a-zA-Z]{2,4})$")) {
            throw  new RE("请输入正确邮箱！");
        }

        if(mobileAppDao.findByEmail(email) == null){
            throw new RE("该邮箱没有被使用！");
        }

        if (forgetPasswordEmailCode.isSend(email)){
            throw  new RE("请不要频繁获取验证码！");
        }

        String code = forgetPasswordEmailCode.create(email);
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject("【警保联动】找回密码");
        message.setText("您本次找回密码的验证码为："+code+" (请在十分钟内完成！)");
        message.setFrom("1563782247@qq.com");
        message.setTo(email);
        try {
            mail.send(message);
            return new R<>("发送成功！");

        }catch (MailException ignored){
            forgetPasswordEmailCode.del(email);
            throw new RE("发送失败，请检查邮箱是否正确！");
        }

    }

    @RequestMapping(value = "/forget/byEmail",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> forgetPassword(@RequestBody Map<String,Object> data){
        String email = (String) data.get("email");
        String code = (String) data.get("code");
        String password = (String) data.get("password");
        if(email == null){
            throw new RE("你没有邮箱！");
        }
        if(code == null){
            throw new RE("请输入验证码！");
        }
        if(password == null){
            throw new RE("请输入密码！");
        }
        if (!forgetPasswordEmailCode.check(email,code)){
            throw new RE("验证码不正确！");
        }
        MobileApp mobileApp = mobileAppDao.findByEmail(email);
        String oldPass = mobileApp.getPassword();
        mobileApp.setPassword(password);
        mobileApp.checkPassword();


        AnYuanServer.passUpdate(mobileApp,oldPass);
        mobileAppDao.save(mobileApp);
        return new R<>("修改成功");
    }

    @RequestMapping(value = "/update",method = {RequestMethod.GET,RequestMethod.POST})
    public R<MobileApp> update(@RequestHeader String authorization, @RequestBody MobileApp curr){
        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        mobileApp.update(curr);
        mobileApp.check();

        AnYuanServer.renew(mobileApp);
        mobileAppDao.save(mobileApp);
        return new R<MobileApp>("修改成功").setData(mobileApp);
    }

    @RequestMapping(value = "/update/password",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> update(@RequestHeader String authorization, @RequestBody Map<String,Object> data){
        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        String password = (String)data.get("password");
        String newPassword = (String)data.get("newPassword");
        if(!mobileApp.getPassword().equals(password)){
            throw new RE("密码错误");
        }
        String old = mobileApp.getPassword();
        mobileApp.setPassword(newPassword);
        mobileApp.checkPassword();

        AnYuanServer.passUpdate(mobileApp,old);
        mobileAppDao.save(mobileApp);
        return new R<>("修改成功");
    }

    @RequestMapping(value = "/register",method = {RequestMethod.GET,RequestMethod.POST})
    public R<MobileApp> register(
            @RequestBody RegisterDto data,
            @RequestHeader(required = false) String deviceId,
            @RequestHeader(required = false) String deviceType){

        MobileApp mobileApp = mobileAppDao.findByAccount(data.account);
        if (mobileApp != null) throw new RE("账号已被注册");


        mobileApp = new MobileApp();
        mobileApp.setAccount(data.account);
        mobileApp.setPassword(data.password);
        mobileApp.setJob(data.job);
        mobileApp.setAddr(data.addr);
        mobileApp.setDeviceId(deviceId);
        mobileApp.setDeviceType(deviceType);
        mobileApp.check();

        AnYuanServer.register(mobileApp);
        mobileAppDao.save(mobileApp);


        AnYuanServer.login(mobileApp);
        String auth = appAuth.save(mobileApp);
        return new R<MobileApp>("注册成功").setData(mobileApp).setAuthorization(auth);
    }

    @RequestMapping(value = "/login",method = {RequestMethod.GET,RequestMethod.POST})
    public R<MobileApp> login(
            @RequestBody Map<String,Object> data,
            @RequestHeader(required = false) String deviceId,
            @RequestHeader(required = false) String deviceType){
        String account = (String) data.get("account");
        String password = (String) data.get("password");
        MobileApp mobileApp = mobileAppDao.findMobileAppByAccountAndPassword(account, password);
        if (mobileApp == null) throw new RE("账号或密码错误");
        /*通知下线*/
        onlinePush.send(mobileApp,new LogoutOP());


        mobileApp.setDeviceId(deviceId);
        mobileApp.setDeviceType(deviceType);
        mobileAppDao.save(mobileApp);

        String auth = appAuth.save(mobileApp);
        AnYuanServer.login(mobileApp);

        return new R<MobileApp>("登录成功").setData(mobileApp).setAuthorization(auth);
    }

    @RequestMapping(value = "/logout",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> logout(@RequestHeader String authorization){

        MobileApp mobileApp = mobileAppService.get(authorization);
        if (mobileApp != null) {
            mobileApp.setDeviceId(null);
            mobileApp.setDeviceType(null);
            mobileAppDao.save(mobileApp);
            appAuth.del(mobileApp);
            appOline.del(mobileApp.getId());
        }

        return new R<>("成功登出");
    }

    @RequestMapping(value = "/delete",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> delete(@RequestBody Map<String,Object> data){
        String account = (String) data.get("account");
        String password = (String) data.get("password");
        MobileApp mobileApp = mobileAppDao.findByAccount(account);
        if (!mobileApp.getPassword().equals(password)){
            throw new RE("密码错误");
        }

        AnYuanServer.destroy(mobileApp);
        mobileAppDao.delete(mobileApp);

        return new R<>("成功注销");
    }





    @RequestMapping(value = "/auth",method = {RequestMethod.GET,RequestMethod.POST})
    public R<MobileApp> auth(
            @RequestHeader String authorization,
            @RequestHeader(required = false) String deviceId,
            @RequestHeader(required = false) String deviceType){

        /* 检查登录 */
        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        mobileApp.setDeviceType(deviceType);
        mobileApp.setDeviceId(deviceId);
        mobileAppDao.save(mobileApp);
        return new R<MobileApp>("您已登录").setData(mobileApp);
    }

    @RequestMapping(value = "/units",method = {RequestMethod.GET,RequestMethod.POST})
    public R<List<Unit>> myUnits(@RequestHeader String authorization) {
        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        List<Unit> units = mobileAppUnitDao.getUnits(mobileApp);
        units.forEach(var-> var.setIsJoin(true));
        return new R<List<Unit>>("查询成功").setData(units);
    }

    @RequestMapping(value = "/units/same",method = {RequestMethod.GET,RequestMethod.POST})
    public R<List<Unit>> aaa(@RequestHeader String authorization, @RequestBody Map map) {
        Integer mobileAppId = (Integer) map.get("mobileAppId");

        MobileApp mobileApp = mobileAppService.checkLogin(authorization);


        MobileApp byId = mobileAppDao.findById(mobileAppId).orElse(null);
        if (byId == null) throw new RE("找不到该用户");
        List<Unit> units = new ArrayList<>();
        for (MobileAppUnit mobileAppUnit1 : mobileApp.getMobileAppUnits()) {
            for (MobileAppUnit mobileAppUnit2 : byId.getMobileAppUnits()) {
                if (Objects.equals(mobileAppUnit1.getUnit().getId(), mobileAppUnit2.getUnit().getId())) {
                    units.add(mobileAppUnit1.getUnit());
                }
            }
        }


        return new R<List<Unit>>("查询成功").setData(units);
    }

    @RequestMapping(value = "/alarms",method = {RequestMethod.GET,RequestMethod.POST})
    public R<List<Alarm>> myAlarms(@RequestHeader String authorization) {
        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        List<Alarm> alarms = mobileAppAlarmDao.getAlarms(mobileApp, PageRequest.of(0, 100));
        return new R<List<Alarm>>("查询成功").setData(alarms);
    }


    @RequestMapping(value = "/online",method = {RequestMethod.GET,RequestMethod.POST})
    public R<List<MobileApp>> online() {

        return new R<List<MobileApp>>("查询成功").setData(appOline.getMobileApps());
    }


    @RequestMapping(value = "/alarm/clear",method = {RequestMethod.GET,RequestMethod.POST})
    public R<String> stop(@RequestHeader String authorization){
        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        mobileApp.setNowAlarm(null);
        mobileAppDao.save(mobileApp);

        return new R<>("ok");
    }

    @RequestMapping(value = "/alarm/now",method = {RequestMethod.GET,RequestMethod.POST})
    public R<Alarm> now(@RequestHeader String authorization){
        MobileApp mobileApp = mobileAppService.checkLogin(authorization);
        Alarm nowAlarm = mobileApp.getNowAlarm();
        if (nowAlarm == null) throw new RE("当前没有警报");
        return new R<Alarm>("ok").setData(nowAlarm);
    }


}
